package game.zqll.systems.input;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;

import java.util.LinkedHashMap;
import java.util.Map;

public class KeyBindings {
    // 定义按键分类枚举类型
    public enum KeyCategory {
        MOVEMENT, SPECIAL
    }

    // 定义按键枚举类型
    public enum Key {
        NONE(KeyCategory.SPECIAL, -1),
        // 移动控制,
        MOVE_LEFT(KeyCategory.MOVEMENT, Input.Keys.A),
        MOVE_RIGHT(KeyCategory.MOVEMENT, Input.Keys.D);

        private KeyCategory category;
        private int keyCode;
        private boolean isMouseButton = false;

        Key(KeyCategory category, int keyCode) {
            this(category, keyCode, false);
        }

        Key(KeyCategory category, int keyCode, boolean isMouseButton) {
            this.category = category;
            this.keyCode = keyCode;
            this.isMouseButton = isMouseButton;
        }

        public KeyCategory getCategory() {
            return category;
        }

        public int getKeyCode() {
            return keyCode;
        }
        }

    // 存储按键映射的Map
    private final static Map<Key, Integer> key2KeyCodeMap = new LinkedHashMap<>();
    private final static Map<Integer, Key> keyCode2KeyMap = new LinkedHashMap<>();

    // 存储第二套按键映射的Map
    private final static Map<Key, Integer> secondaryKey2KeyCodeMap = new LinkedHashMap<>();
    private final static Map<Integer, Key> secondaryKeyCode2KeyMap = new LinkedHashMap<>();

    // 初始化默认按键映射
    static {
        for (Key key : Key.values()) {
            key2KeyCodeMap.put(key, key.getKeyCode());
            keyCode2KeyMap.put(key.getKeyCode(), key);

            // 初始化第二套按键为NONE
            secondaryKey2KeyCodeMap.put(key, Key.NONE.getKeyCode());
            secondaryKeyCode2KeyMap.put(Key.NONE.getKeyCode(), key);
        }
    }

    // 获取按键映射
    public static boolean isKeyPressed(Key key) {
        // 获取主按键的状态
        int primaryKeyCode = key2KeyCodeMap.get(key);
        boolean primaryPressed = isKeyCodePressed(primaryKeyCode);

        // 获取副按键的状态
        int secondaryKeyCode = secondaryKey2KeyCodeMap.get(key);
        boolean secondaryPressed = secondaryKeyCode != Key.NONE.getKeyCode() &&
            isKeyCodePressed(secondaryKeyCode);

        return primaryPressed || secondaryPressed;
    }

    public static boolean isKeyJustPressed(Key key) {
        // 获取主按键的状态
        int primaryKeyCode = key2KeyCodeMap.get(key);
        boolean primaryJustPressed = isKeyCodeJustPressed(primaryKeyCode);

        // 获取副按键的状态
        int secondaryKeyCode = secondaryKey2KeyCodeMap.get(key);
        boolean secondaryJustPressed = secondaryKeyCode != Key.NONE.getKeyCode() &&
            isKeyCodeJustPressed(secondaryKeyCode);

        return primaryJustPressed || secondaryJustPressed;
    }

    // 添加新的辅助方法来处理键码
    private static boolean isKeyCodePressed(int keyCode) {
        if (keyCode > Input.Keys.MAX_KEYCODE) {
            // 处理鼠标按键，注意这里的转换要与 Key 枚举中的定义一致
            int mouseButton = keyCode - Input.Keys.MAX_KEYCODE - 1;
            return mouseButton >= 0 && mouseButton < 5 && Gdx.input.isButtonPressed(mouseButton);
        } else {
            return Gdx.input.isKeyPressed(keyCode);
        }
    }

    private static boolean isKeyCodeJustPressed(int keyCode) {
        if (keyCode > Input.Keys.MAX_KEYCODE) {
            // 处理鼠标按键，注意这里的转换要与 Key 枚举中的定义一致
            int mouseButton = keyCode - Input.Keys.MAX_KEYCODE - 1;
            return mouseButton >= 0 && mouseButton < 5 && Gdx.input.isButtonJustPressed(mouseButton);
        } else {
            return Gdx.input.isKeyJustPressed(keyCode);
        }
    }

    public static Key key(int keyCode) {
        // 先检查主按键映射
        Key primaryKey = keyCode2KeyMap.getOrDefault(keyCode, Key.NONE);
        if (primaryKey != Key.NONE) {
            return primaryKey;
        }
        // 如果主按键没找到，检查副按键映射
        return secondaryKeyCode2KeyMap.getOrDefault(keyCode, Key.NONE);
    }

    public static int keyCode(Key key) {
        // 获取主按键的键码
        int primaryKeyCode = key2KeyCodeMap.getOrDefault(key, Key.NONE.keyCode);
        if (primaryKeyCode != Key.NONE.keyCode) {
            return primaryKeyCode;
        }
        // 如果主按键是NONE，则返回副按键的键码
        return secondaryKey2KeyCodeMap.getOrDefault(key, Key.NONE.keyCode);
    }

    // 设置按键映射
    public static void keyCode(Key key, int keyCode) {
        Integer lastKeyCode = key2KeyCodeMap.remove(key);
        Key removeKey = keyCode2KeyMap.remove(lastKeyCode);
        key2KeyCodeMap.put(key, keyCode);
        keyCode2KeyMap.put(keyCode, key);
    }

    // 获取第二套按键
    public static int getSecondaryKeyCode(Key key) {
        return secondaryKey2KeyCodeMap.getOrDefault(key, Key.NONE.keyCode);
    }

    // 设置第二套按键
    public static void setSecondaryKeyCode(Key key, int keyCode) {
        secondaryKey2KeyCodeMap.put(key, keyCode);
        secondaryKeyCode2KeyMap.put(keyCode, key);
    }

    // 获取指定分类的按键列表
    public static Map<Key, Integer> getKeyMapByCategory(KeyCategory category, boolean isSecondary) {
        Map<Key, Integer> categoryKeyMap = new LinkedHashMap<>();
        Map<Key, Integer> sourceMap = isSecondary ? secondaryKey2KeyCodeMap : key2KeyCodeMap;

        for (Key key : sourceMap.keySet()) {
            if (key.getCategory() == category) {
                categoryKeyMap.put(key, sourceMap.get(key));
            }
        }
        return categoryKeyMap;
    }

    // 获取按键分类列表。分组按键，如：UI的设置界面
    public static KeyCategory[] getKeyCategories() {
        return KeyCategory.values();
    }

    public static boolean isKeyCodeConflict(Key key, int keyCode, boolean isSecondary) {
        if (keyCode == Key.NONE.getKeyCode()) {
            return false;
        }

        for (Key existingKey : Key.values()) {
            if (existingKey != key) {
                if (isSecondary) {
                    if (getSecondaryKeyCode(existingKey) == keyCode) {
                        return true;
                    }
                } else {
                    if (keyCode(existingKey) == keyCode) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public static void setPrimaryKeyCode(Key key, int keyCode) {
        keyCode(key, keyCode);
    }
}

